package org.haifi.game.channel;

import java.lang.reflect.Method;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.core.session.IoSession;
import org.haifi.game.action.GameBaseAction;
import org.haifi.game.compiler.GameCmdInvokerFactory;
import org.haifi.game.reflection.GameReflect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.collect.Maps;
import com.google.protobuf.MessageLite;

/**
 * 接收客户端及服务器发送的指令，并分发给对应的线程池进行调用
 * 
 * @author joycube2
 * 
 */
@Component
public class GameProcesser {

	// 可能，只能直接调用系统的功能吧。TODO:也不一定，查一下fengshen中的npc的攻击
	// /**
	// * 分发消息(指令id,可以通过GameReflect获得)
	// *
	// * 主要供游戏系统使用
	// *
	// * @param obj
	// * action.method接收的参数
	// */
	// public void process(IoSession ioSession, Object obj) {
	// // commandId可以从obj中反射获得
	// process(ioSession, GameReflect.getParamCmdId(obj.getClass()), obj);
	// }

	@PostConstruct
	public void init() {
		gameCmdInvokers = Maps.newConcurrentMap();
		gameCmdInvokers.putAll(gameCmdInvokerFactory.generateGameCmdInvoker());
	}

	/**
	 * 分发消息
	 * 
	 * 主要供GameIoHandler使用
	 * 
	 * @param cmdId
	 * @param obj
	 */
	public void process(IoSession ioSession, short cmdId, MessageLite obj) {
		// 这里应该加入，如果是用户队列消息，应该丢给

		if (userAction) {
			// 使用动态生成类处理
			GameProcesserActionRunnable runnable = new GameProcesserActionRunnable();
			runnable.invoker = gameCmdInvokers.get(cmdId);
			runnable.param = obj;
			runnable.ioSession = ioSession;

			// 丢入线程池
			gameExecutorRouter.execute(cmdId, runnable);
		} else {
			// 使用反射处理
			GameBaseAction action = GameReflect.getGameBaseAction(cmdId);
			Method method = GameReflect.getMethod(cmdId);
			GameProcesserReflectRunnable runnable = new GameProcesserReflectRunnable();
			runnable.gameBaseAction = action;
			runnable.method = method;
			runnable.param = obj;
			runnable.ioSession = ioSession;

			// 丢入线程池
			gameExecutorRouter.execute(cmdId, runnable);
		}

		if (log.isDebugEnabled()) {
			log.debug("add executor:" + ioSession + "\t" + cmdId);
		}
	}

	// @Autowired
	// private ThreadPoolTaskExecutor readTaskExecutor;

	/**
	 * true:使用动态生成类直接调用
	 * 
	 * false:使用反射类进行调用
	 */
	public boolean userAction = true;

	private Map<Short, GameCmdInvoker> gameCmdInvokers;

	@Autowired
	private GameExecutorRouter gameExecutorRouter;

	@Autowired
	private GameCmdInvokerFactory gameCmdInvokerFactory;

	private static final Log log = LogFactory.getLog(GameProcesser.class);
}
